﻿#include "HalconLineFindWidget.h"
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QLabel>
#include <QApplication>
#include "ImageCommon.h"
#pragma execution_character_set("utf-8")
HalconLineFindWidget::HalconLineFindWidget(QWidget *parent)
    : QWidget{parent}
{
    HalconCpp::SetSystem("clip_region","false");
    setupUI();
    initUI();
    initConnection();
}

void HalconLineFindWidget::setImage(const QImage &img)
{
    mImg = img;
    wgtRoiLineFind->setImage(mImg);
}

LineFindParam HalconLineFindWidget::getParam()
{
    updateLineFindPar();
    return mParam;
}

void HalconLineFindWidget::setParam(const LineFindParam &par)
{
    mParam = par;
    wgtRoiLineFind->setItem(new ItemCaliper(mParam.caliper.x1, mParam.caliper.y1, mParam.caliper.x2, mParam.caliper.y2, mParam.caliper.height));

    spboxPointNum->setValue(mParam.pointNum);
    spboxPointFindWidth->setValue(mParam.pointCheckWidth);
    cbboxLinePolarity->setCurrentText(mParam.polarity.S().ToLocal8bit());
    cbboxLineSelect->setCurrentText(mParam.selectEdge.S().ToLocal8bit());
    dspboxMeasureThr->setValue(mParam.measureThr);
    dspboxMeasureSigma->setValue(mParam.measureSigma);
    dspboxMinScore->setValue(mParam.minScore);
}
template <typename T1, typename T2>
void configValueBox(T2* box, T1 min, T1 max, T1 singleStep, T1 defaultValue) {
    box->setRange(min, max);
    box->setSingleStep(singleStep);
    box->setValue(defaultValue);
}
void HalconLineFindWidget::setupUI()
{
    wgtRoiLineFind = new WidgetRoiDraw();
    wgtRoiLineFind->setMode(RWM_LineFind);
    spboxPointNum = new QSpinBox();
    spboxPointFindWidth = new QSpinBox();
    cbboxLinePolarity = new QComboBox();
    cbboxLineSelect = new QComboBox();
    dspboxMinScore = new QDoubleSpinBox();
    dspboxMeasureThr = new QDoubleSpinBox();
    dspboxMeasureSigma = new QDoubleSpinBox();
    pbtnLineFind = new QPushButton("查找");

    configValueBox(spboxPointNum, 10, 10000, 1, 50);
    configValueBox(spboxPointFindWidth, 2, 10000, 1, 10);
    configValueBox(dspboxMinScore, 0.01, 1.0, 0.1, 0.7);
    configValueBox(dspboxMeasureThr, 1.0, 255.0, 1.0, 10.0);
    configValueBox(dspboxMeasureSigma, 0.1, 100.0, 1.0, 3.0);

    cbboxLinePolarity->addItems({"all", "negative", "positive"});
    cbboxLineSelect->addItems({"all", "last", "first"});

    QHBoxLayout* hLayout = new QHBoxLayout();
    this->setLayout(hLayout);
    hLayout->addWidget(wgtRoiLineFind);
    {
        QVBoxLayout* vLayout = new QVBoxLayout();
        hLayout->addLayout(vLayout);
        vLayout->addWidget(new QLabel("特征点数量"));
        vLayout->addWidget(spboxPointNum);
        vLayout->addWidget(new QLabel("特征点查找宽度"));
        vLayout->addWidget(spboxPointFindWidth);
        vLayout->addWidget(new QLabel("极性"));
        vLayout->addWidget(cbboxLinePolarity);
        vLayout->addWidget(new QLabel("查找选择"));
        vLayout->addWidget(cbboxLineSelect);
        vLayout->addWidget(new QLabel("最小分数"));
        vLayout->addWidget(dspboxMinScore);
        vLayout->addWidget(new QLabel("边缘强度"));
        vLayout->addWidget(dspboxMeasureThr);
        vLayout->addWidget(new QLabel("平滑系数"));
        vLayout->addWidget(dspboxMeasureSigma);
        vLayout->addWidget(pbtnLineFind);
        vLayout->addStretch();
    }
}

void HalconLineFindWidget::initUI()
{
    spboxPointNum->setValue(50);
    spboxPointFindWidth->setValue(20);
    cbboxLinePolarity->setCurrentText("all");
    cbboxLineSelect->setCurrentText("all");
    dspboxMinScore->setValue(0.5);
    dspboxMeasureThr->setValue(5);
    dspboxMeasureSigma->setValue(3);
}

void HalconLineFindWidget::initConnection()
{
    connect(pbtnLineFind, &QPushButton::clicked, this, [&](){
        updateLineFindPar();
        //训练模板
        HObject modelImage = ImageCommon::imageToHImage(mImg);
        mParam.image = modelImage;
        LineFindResult result = QtHalcon::findLine(mParam);
        if(!(result.lineParameter.TupleLength()>0))
            return;
        wgtRoiLineFind->getView()->clearDraw();
        for(int i = 0; i < result.pointRow.TupleLength(); ++i){
            wgtRoiLineFind->getView()->drawItem->addPoint(QPointF(result.pointCol[i].D(), result.pointRow[i].D()));
        }
        for(int i = 0; i < result.findRectRow.TupleLength(); ++i){
            wgtRoiLineFind->getView()->drawItem->addRectR(QPointF(result.findRectCol[i].D(), result.findRectRow[i].D()),
                                                                 result.findRectPhi[i].D(), result.findRectLen1[i].D(), result.findRectLen2[i].D());
        }
        QPointF point[2] = {QPointF(result.lineParameter[1], result.lineParameter[0]), QPointF(result.lineParameter[3], result.lineParameter[2])};
        wgtRoiLineFind->getView()->drawItem->addLine(QLineF(point[0], point[1]));
    });
}
void HalconLineFindWidget::updateLineFindPar()
{
    static_cast<ItemCaliper*>(wgtRoiLineFind->getItem())->getDefObject(mParam.caliper);
    mParam.pointNum = spboxPointNum->value();
    mParam.pointCheckWidth = spboxPointFindWidth->value();
    mParam.polarity = cbboxLinePolarity->currentText().toLocal8Bit().data();
    mParam.selectEdge = cbboxLineSelect->currentText().toLocal8Bit().data();
    mParam.measureThr = dspboxMeasureThr->value();
    mParam.measureSigma = dspboxMeasureSigma->value();
    mParam.minScore = dspboxMinScore->value();
}
